﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Luna;
using System.IO;
using Luna.Framework;

namespace VulnDBExplorer.Services.Impl {
	
	public class Repository: IContextAwareObject, IUriResolver, IRepository  {

		private IAppContext context;

		public Repository() {
			Codebases = new List<ICodebase>();
		}

		public IAppContext Context {
			get {
				return context;
			}
			set {
				if (context == null) {
					context = value;
					context.addService(this);
				}
			}
		}

		public string Name {
			get;
			set;
		}

		public string Folder {
			get;
			set;
		}

		public IList<ICodebase> Codebases {
			get;
			private set;
		}

		public override string ToString() {
			return "{0}, {1}: codebases={2}, folder={3}".format(this.GetType().Name, Name, Codebases.Count, Folder);
		}

		bool IUriResolver.supportScheme(string scheme) {
			return "codebase".Equals(scheme);
		}

		object IUriResolver.resolveObject(IAppContext context, Uri uri, object data) {
			string host = uri.Host;
			if (Name.Equals(host, StringComparison.OrdinalIgnoreCase)) {
				string cbname = uri.Segments[1];
				return Codebases.FirstOrDefault(cb => cb.Name.Equals(cbname, StringComparison.OrdinalIgnoreCase));
			}
			return null;
		}
	}

	public abstract class Codebase : ICodebase {

		public static readonly string[] SourceFileExtensions;

		static Codebase() {
			SourceFileExtensions = new string[] { ".h", ".c", ".cpp" };
		}

		public string Name {
			get;
			set;
		}

		public string Folder {
			get;
			set;
		}

		public string Text {
			get;
			set;
		}

		public int VersionID {
			get;
			set;
		}

		public override string ToString() {
			return "{0}, {1}: id={2}, text={3}, folder={4}".format(this.GetType().Name, Name, VersionID, Text, Folder);
		}

		public IEnumerable<string> enumerateSourceFiles() {
			foreach (string fn in Directory.EnumerateFiles(Folder, "*.*", SearchOption.AllDirectories)) {
				string ext = fn.getFileExt();
				if (SourceFileExtensions.indexOf(ext) >= 0)
					yield return fn;
			}
		}

		public abstract string getRelativePath(string filename);

		public abstract string getFullPath(string filename);
	}
}
